library ieee;
use ieee.std_logic_1164.all;
--use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_bit.all;

entity vga_raster_DE0 is
	generic(width: integer := 8);
  port (
    reset : in std_logic;
	 reset_passarinho: in std_logic;
	 colisao : out std_logic;
	 parado : in std_logic;
    clk   : in bit; --25Mhz
    VGA_HS,     -- Sync horizontal - Active-Low 
    VGA_VS: OUT STD_LOGIC; -- Sync vertical - Active-Low 
    VGA_R, VGA_G, VGA_B : out std_logic_vector(3 downto 0);
	 
	 posicao_atual: in integer
  );
end vga_raster_DE0;

architecture rtl of vga_raster_DE0 is
  -- Parametros do Video
  -- tamanho total da linha (em pixels): area do display+front porch+hsync+back porch
  constant HTOTAL       : integer :=  800;
  constant HSYNC        : integer :=  96;
  constant HBACK_PORCH  : integer :=  48;
  constant HACTIVE      : integer :=  640;
  constant HFRONT_PORCH : integer :=  16;
  --tamanho total da coluna (em linhas): area do display+front porch+vsync+back porch 
  constant VTOTAL       : integer :=  525;
  constant VSYNC        : integer :=  2;
  constant VBACK_PORCH  : integer :=  33;
  constant VACTIVE      : integer :=  480;
  constant VFRONT_PORCH : integer :=  10;
  constant RETANGULO_HSTART : integer  := 0;
  constant RETANGULO_HALF   : integer  := 320; -- meio
  constant RETANGULO_HEND   : integer  := 640;
  constant RETANGULO_VSTART : integer  := 0;
  constant RETANGULO_VEND   : integer  := 480;
  
  -- Passarinho --
  -- Area do retangulo horizontal
  constant PASSARINHO_HSTART : integer  := 285;
  constant PASSARINHO_HEND   : integer  := 295;
  -- Area do retangulo vertical
  constant PASSARINHO_VSTART : integer  := 235;
  constant PASSARINHO_VEND   : integer  := 245;
  -- Variaveis Passarinho --
  signal passarinho_h: std_logic;
  signal passarinho_v: std_logic;
  signal passarinho: std_logic;
  
  -- Contador horizontal
  signal Hcount : std_logic_vector(9 downto 0);
  -- Contador vertical
  signal Vcount : std_logic_vector(9 downto 0);
  signal FimdaLinha, FimdoFrame : std_logic;
  signal vga_hblank, vga_hsync,
           vga_vblank, vga_vsync : std_logic;  
  signal retangulo_h, retangulo_v, retangulo, coluna_1, coluna_1_V, coluna_1_H, coluna_2, coluna_2_H, coluna_3_H, coluna_4_H, coluna_3, coluna_2_V, coluna_4, coluna_3_V, coluna_5_H, coluna_6_H, coluna_5, coluna_6, coluna_4_V, coluna_7_H, coluna_8_H, coluna_7, coluna_8 : std_logic;  -- area do retangulo
  --signal clk  : bit;
  type cores is (red,green,blue);
  signal estado_atual, proximo_estado : cores;
  signal deslocamento, deslocamento2, deslocamento3, deslocamento4 : integer;
  signal deslocamentoH_1, deslocamentoH_2, deslocamentoH_3, deslocamentoH_4 : integer;
  
  -- Valor randomico
  signal random_num1 : integer := 0;

begin

Randomico: 	process(clk)
					variable rand_temp : bit_vector(width-1 downto 0):=(width-1 => '1',others => '0');
					variable temp : bit := '0';
				begin
					if clk = '1' then
						temp := rand_temp(width-1) xor rand_temp(width-2);
						rand_temp(width-1 downto 1) := rand_temp(width-2 downto 0);
						rand_temp(0) := temp;
					end if;
					-- Numero aleatorio gerado --
					random_num1 <= to_integer(unsigned(rand_temp));
				end process;

				
-- ****************************************************************
-- 	INICIO DO CALCULO DE ONDE O PASSARINHO COMECA E TERMINA
-- ****************************************************************
	
	PassarinhoH : process (clk, reset)
	begin
	  if reset = '1' then
		 passarinho_h <= '1';
	  elsif clk'event and clk = '1' then
		 if Hcount = HSYNC + HBACK_PORCH + PASSARINHO_HSTART then
			passarinho_h <= '1';
		 elsif Hcount = HSYNC + HBACK_PORCH + PASSARINHO_HEND then
			passarinho_h <= '0';
		 end if;
	  end if;
	end process PassarinhoH;

	PassarinhoV : process (clk, reset, posicao_atual)
	begin
	  if reset = '1' then
		 passarinho_v <= '0';
	  elsif clk'event and clk = '1' then
		 if FimdaLinha = '1' then
			if Vcount = VSYNC + VBACK_PORCH - 1 + PASSARINHO_VSTART - posicao_atual then
			  passarinho_v <= '1';
			elsif Vcount = VSYNC + VBACK_PORCH - 1 + PASSARINHO_VEND - posicao_atual then
			  passarinho_v <= '0';
			end if;
		 end if;
	  end if;
	end process PassarinhoV;

	passarinho <= passarinho_h and passarinho_v;

-- ****************************************************************
-- 	FIM
-- ****************************************************************				


HCounter : process (clk, reset)
begin
  if reset = '1' then
    Hcount <= (others => '0');
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      Hcount <= (others => '0');
    else
      Hcount <= Hcount + 1;
    end if;
  end if;
end process HCounter;

FimdaLinha <= '1' when Hcount = HTOTAL - 1 else '0';

VCounter: process (clk, reset)
begin
  if reset = '1' then
    Vcount <= (others => '0');
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if FimdoFrame = '1' then
         Vcount <= (others => '0');
      else
         Vcount <= Vcount + 1;
      end if;
    end if;
  end if;
end process VCounter;

 FimdoFrame <= '1' when Vcount = VTOTAL - 1 else '0';
 
HSyncGen : process (clk, reset)
begin
  if reset = '1' then
    vga_hsync <= '1';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      vga_hsync <= '1';
    elsif Hcount = HSYNC - 1 then
      vga_hsync <= '0';
    end if;
  end if;
end process HSyncGen;

HBlankGen : process (clk, reset)
begin
  if reset = '1' then
    vga_hblank <= '1';
  elsif clk'event and clk = '1' then
    if Hcount = HSYNC + HBACK_PORCH then
      vga_hblank <= '0';
    elsif Hcount = HSYNC + HBACK_PORCH + HACTIVE then
      vga_hblank <= '1';
    end if;
  end if;
end process HBlankGen;

VSyncGen : process (clk, reset)
begin
  if reset = '1' then
    vga_vsync <= '1';
  elsif clk'event and clk = '1' then
    if FimdaLinha ='1' then
      if FimdoFrame = '1' then
        vga_vsync <= '1';
      elsif Vcount = VSYNC - 1 then
        vga_vsync <= '0';
      end if;
    end if;
  end if;
end process VSyncGen;

VBlankGen : process (clk, reset)
begin
  if reset = '1' then
    vga_vblank <= '1';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 then
        vga_vblank <= '0';
      elsif Vcount = VSYNC + VBACK_PORCH + VACTIVE - 1 then
        vga_vblank <= '1';
      end if;
    end if;
  end if;
end process VBlankGen;

RectangleHGen : process (clk,reset)--tela fundo vertical
begin
  if reset = '1' then
    retangulo_h <= '1';
  elsif clk'event and clk = '1' then
    if Hcount = (HSYNC + HBACK_PORCH + RETANGULO_HSTART) then
      retangulo_h <= '1';
    elsif (Hcount = HSYNC + HBACK_PORCH + RETANGULO_HEND) then
      retangulo_h <= '0';
    end if;
  end if;
end process RectangleHGen;

RectangleVGen : process (clk, reset)--Tela fundo horizontal
begin
  if reset = '1' then
    retangulo_v <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + RETANGULO_VSTART then
        retangulo_v <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + RETANGULO_VEND then
        retangulo_v <= '0';
      end if;
    end if;
  end if;
end process RectangleVGen;

p_coluna: process(clk, reset_passarinho,parado)-- processo para controlar Colunas
VARIABLE i, s, j, k, q, w, l  : natural;
begin
	if reset_passarinho = '1' then
	
		deslocamento <= 0;
		deslocamento2 <= 0;
		deslocamento3 <= 0;
		deslocamento4 <= 0;
		
		deslocamentoH_1 <= 0;
		deslocamentoH_2 <= 0;
		deslocamentoH_3 <= 0;
		deslocamentoH_4 <= 0;
		
		i := 0;
		s := 0;
		j := 0;
		k := 0;
		q := 0;
		w := 0;
		l := 0;
		
	elsif parado = '0' then
	
		deslocamento <= 0;
		deslocamento2 <= 0;
		deslocamento3 <= 0;
		deslocamento4 <= 0;

		deslocamentoH_1 <= 0;
		deslocamentoH_2 <= 0;
		deslocamentoH_3 <= 0;
		deslocamentoH_4 <= 0;
		
		i := 0;
		s := 0;
		j := 0;
		k := 0;
		q := 0;
		w := 0;
		l := 0;
		
	elsif clk'event and clk = '1' then
	
		i := i + 1;
		
		if l = 0 then
			deslocamentoH_1 <= random_num1;
			deslocamentoH_2 <= random_num1;
			deslocamentoH_3 <= random_num1;
			deslocamentoH_4 <= random_num1;
			l := l + 1;
		end if;

		if i = 200_000 then

			deslocamento <= deslocamento + 1;
			deslocamento2 <= deslocamento2 + 1;
			deslocamento3 <= deslocamento3 + 1;
			deslocamento4 <= deslocamento4 + 1;

			i:= 0;
			j := j + 1;
			s := s + 1;
			k := k + 1;
			q := q + 1;
			w := w + 1;
						
			if s = 160 then
				deslocamento2 <= deslocamento2 - 160;
				deslocamentoH_2 <= random_num1;
				k := 0;
			end if;

			if s = 320 then
				deslocamento3 <= deslocamento3 - 320;
				deslocamentoH_3 <= random_num1;
				q := 0;
			end if;

			if s = 480 then
				deslocamento4 <= deslocamento4 - 480;
				deslocamentoH_4 <= random_num1;
				w := 0;
			end if;

			if w = 640 then
				deslocamento4 <= 0;
				deslocamentoH_4 <= random_num1;
				w := 0;
				s := 500;
			end if;
			
			if q = 640 then
				deslocamento3 <= 0;
				deslocamentoH_3 <= random_num1;
				q := 0;
			end if;
			
			if k = 640 then
				deslocamento2 <= 0;
				deslocamentoH_2 <= random_num1;
				k := 0;
			end if;

			if j = 640 then
				deslocamento <= 0;
				deslocamentoH_1 <= random_num1;
				j := 0;
			end if;
		else
			deslocamento <= deslocamento;
			deslocamento2 <= deslocamento2;
			deslocamento3 <= deslocamento3;
			deslocamento4 <= deslocamento4;
		end if;
	end if;
end process;

-- Primeira coluna
coluna_V_1 : process (clk,reset_passarinho,deslocamento) -- processo da coluna do bixo horizontal
begin
  if reset_passarinho = '1' then
    coluna_1_V <= '0';
  elsif clk'event and clk = '1' then
    if Hcount = HSYNC + HBACK_PORCH + 575 - deslocamento then
      coluna_1_V <= '1';
    elsif Hcount = HSYNC + HBACK_PORCH + 640 - deslocamento then
      coluna_1_V <= '0';
    end if;
  end if;
end process coluna_V_1;

coluna_H_1 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_1_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 100 + deslocamentoH_1 then
        coluna_1_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + RETANGULO_VEND then
        coluna_1_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_1;

coluna_H_2 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_2_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 0 then
        coluna_2_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + 1 + deslocamentoH_1 then
        coluna_2_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_2;

--Termina primeira Coluna

-- começa segunda coluna
coluna_V_2 : process (clk, reset_passarinho, deslocamento2) -- processo da coluna do bixo horizontal
begin
  if reset_passarinho = '1' then
    coluna_2_V <= '0';
  elsif clk'event and clk = '1' then
    if Hcount = HSYNC + HBACK_PORCH + 575 - deslocamento2 then
      coluna_2_V <= '1';
    elsif Hcount = HSYNC + HBACK_PORCH + 640 - deslocamento2 then
      coluna_2_V <= '0';
    end if;
  end if;
end process coluna_V_2;

coluna_H_3 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_3_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 100 + deslocamentoH_2 then
        coluna_3_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + RETANGULO_VEND then
        coluna_3_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_3;

coluna_H_4 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_4_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 0 then
        coluna_4_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + 1 + deslocamentoH_2 then
        coluna_4_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_4;
--Termina segunda Coluna

-- começa terceira coluna
coluna_V_3 : process (clk, reset_passarinho, deslocamento3) -- processo da coluna do bixo horizontal
begin
  if reset_passarinho = '1' then
    coluna_3_V <= '0';
  elsif clk'event and clk = '1' then
    if Hcount = HSYNC + HBACK_PORCH + 575 - deslocamento3 then
      coluna_3_V <= '1';
    elsif Hcount = HSYNC + HBACK_PORCH + 640 - deslocamento3 then
      coluna_3_V <= '0';
    end if;
  end if;
end process coluna_V_3;

coluna_H_5 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_5_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 100 + deslocamentoH_3 then
        coluna_5_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + RETANGULO_VEND then
        coluna_5_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_5;

coluna_H_6 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_6_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 0 then
        coluna_6_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + 1 + deslocamentoH_3 then
        coluna_6_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_6;
--Termina segunda Coluna

-- começa terceira coluna
coluna_V_4 : process (clk, reset_passarinho, deslocamento4) -- processo da coluna do bixo horizontal
begin
  if reset_passarinho = '1' then
    coluna_4_V <= '0';
  elsif clk'event and clk = '1' then
    if Hcount = HSYNC + HBACK_PORCH + 575 - deslocamento4 then
      coluna_4_V <= '1';
    elsif Hcount = HSYNC + HBACK_PORCH + 640 - deslocamento4 then
      coluna_4_V <= '0';
    end if;
  end if;
end process coluna_V_4;

coluna_H_7 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_7_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 100 + deslocamentoH_4 then
        coluna_7_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + RETANGULO_VEND then
        coluna_7_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_7;

coluna_H_8 : process (clk, reset_passarinho) -- processo da coluna vertical
begin
  if reset_passarinho = '1' then
    coluna_8_H <= '0';
  elsif clk'event and clk = '1' then
    if FimdaLinha = '1' then
      if Vcount = VSYNC + VBACK_PORCH - 1 + 0 then
        coluna_8_H <= '1';
      elsif Vcount = VSYNC + VBACK_PORCH - 1 + 1 + deslocamentoH_4 then
        coluna_8_H <= '0';
      end if;
    end if;
  end if;
end process coluna_H_8;
--Termina segunda Coluna

retangulo <= retangulo_h and retangulo_v; -- Tela de fundo
coluna_1 <= coluna_1_V and coluna_1_H and  parado; -- coluna do bixo
coluna_2 <= coluna_1_V and coluna_2_H and  parado;
coluna_3 <= coluna_2_V and coluna_3_H and  parado;
coluna_4 <= coluna_2_V and coluna_4_H and  parado;
coluna_5 <= coluna_3_V and coluna_5_H and  parado;
coluna_6 <= coluna_3_V and coluna_6_H and  parado;
coluna_7 <= coluna_4_V and coluna_7_H and  parado;
coluna_8 <= coluna_4_V and coluna_8_H and  parado;
colisao <= passarinho and (coluna_1 or coluna_2 or coluna_3 or coluna_4 or coluna_5 or coluna_6 or coluna_7 or coluna_8);

VideoOut: process (clk, reset)
begin
  if reset = '1' then
    VGA_R <= "0000";
    VGA_G <= "0000";
    VGA_B <= "0000";
  elsif clk'event and clk = '1' then

    if retangulo = '1' then
	 
			VGA_R <= "0000";
			VGA_G <= "0000";
			VGA_B <= "1111";
	
			if coluna_1 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;

			if coluna_2 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;
			
			if coluna_3 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;

			if coluna_4 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;

			if coluna_5 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;
			
			if coluna_6 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;

			if coluna_7 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;
			
			if coluna_8 = '1' then
				VGA_R <= "0000";
				VGA_G <= "1111";
				VGA_B <= "0000";
			end if;
			
			if passarinho = '1' then
			
				VGA_R <= "1111";
				VGA_G <= "1111";
				VGA_B <= "0000";
				
			end if;

    elsif vga_hblank = '0' and vga_vblank ='0' then
      VGA_R <= "1111";
      VGA_G <= "1111";
      VGA_B <= "1111";
    else
      VGA_R <= "0000";
      VGA_G <= "0000";
      VGA_B <= "0000";
    end if;
  end if;
end process VideoOut;

VGA_HS <= not vga_hsync;
VGA_VS <= not vga_vsync;

end rtl;